//
// Created by Administrator on 2021/6/11.
//

#ifndef COMPILER_LEXICALANALYZER_H
#define COMPILER_LEXICALANALYZER_H

string str_id[] = {"CONST","VAR","PROCEDURE","BEGIN","END","ODD","IF","THEN","CALL","WHILE","DO","READ","WRITE"};
string out,line;

bool checkId(string s){//检查是否为关键字
    for (int i=0;i<=12;i++){ //查询13个关键字是否匹配
        if (str_id[i] == s){
            return true;
        }
    }
    return false;
}
string upper(string s){//将读入的s中的小写字符全部转换为大写
    for (string::size_type i = 0; i < s.length(); ++i){
        if(s[i] >= 'a' && s[i] <= 'z')
            s[i] -= 32;
    }
    return s;
}

bool skip(char ch){//用于处理该字符是否要保留
    int ret = (
            ch =='=' || ch == ':' || ch == '+' || ch =='-' || ch=='*' ||ch=='/' ||ch =='#' ||ch =='<' ||ch=='>'
            || ch ==';' || ch==',' || ch=='.' || ch=='(' || ch==')' || (ch>='a' && ch <='z') ||(ch>='A' && ch <='Z')
            || (ch>='0' && ch <='9')
    );
    if (ret == 0 && ch > 32) {
        cout<<"Lexical Error"<<endl;
        exit(0);
    }
    return ret;
}

bool checkSymbol(char ch){//检查是否为运算符/分界符
    return ch =='=' || ch == ':' || ch == '+' || ch =='-' || ch=='*' ||ch=='/' ||ch =='#' ||ch =='<' ||ch=='>'
           || ch ==';' || ch==',' || ch=='.' || ch=='(' || ch==')';
}

int calcKeyword(int point,vector<string>& sym, vector<string>& label){//处理关键字+标识符
    if (point < 0 || point >= line.length()) return point;//当前point指针超出边界
    while (point < line.length() && !skip(line[point])) point++;//处理非法字符
    if (point == line.length() || !((line[point] >= 'a' && line[point] <= 'z') || (line[point] >= 'A' && line[point] <= 'Z'))){
        //当前第一个字符不为字母直接跳出
        return point;
    }
    int headPoint=point;//记录下头部指针
    //找到标识符尾部（大小写字母+数字）
    while (point < line.length() && ((line[point] >= 'a' && line[point] <= 'z') || (line[point] >= 'A' && line[point] <= 'Z') || (line[point] >= '0' && line[point] <= '9')))
        point++;
    if (point - headPoint > 10){
        //超过十个字母
        cout<<"Lexical Error"<<endl;
        return -1;
    }

    string str = line.substr(headPoint,point-headPoint);//截取字符串
    str = upper(str);//全部转换为大写
    if (checkId(str)){//检查是否为关键字
        sym.push_back("Keyword");
        label.push_back(str);
        out += str;
        out += "\n";
    }else {//为标识符
        sym.push_back("Identifier");
        label.push_back(str);
        out += "IDENTIFIER ";
        out += str;
        out += "\n";
    }
    return point;//返回当前处理到的位置
}

int calcNumber(int point,vector<string>& sym, vector<string>& label){
    if (point < 0 || point >= line.length()) return point;//同上
    while (point < line.length() && !skip(line[point])) point++;//同上
    if (point == line.length() || !(line[point] >= '0' && line[point] <= '9')){//当前第一个字符不为数字
        return point;
    }
    int headPoint=point;
    while (point < line.length() && (line[point] >= '0' && line[point] <= '9'))//找到连续的数字
        point++;
    if (point < line.length() && ((line[point] >= 'a' && line[point] <= 'z') || (line[point] >= 'A' && line[point] <= 'Z'))){
        //此时的下一个字符为字母
        cout<<"Lexical Error"<<endl;
        return -1;
    }
    //用于处理前导0
    while (line[headPoint] == '0') headPoint++;
    string str = line.substr(headPoint,point-headPoint);
    if (headPoint == point) str = "0";//相等说明该数字为0
    sym.push_back("Number");
    label.push_back(str);
    out += "NUMBER ";
    out += str;
    out += "\n";
    return point;
}

int calcSymbol(int point,vector<string>& sym, vector<string>& label){
    if (point < 0 || point >= line.length()) return point;//同上
    while (point < line.length() && !skip(line[point])) point++;//同上
    if (point == line.length() || !checkSymbol(line[point])){//当前第一个符号不为分界符或运算符
        return point;
    }
    if (line[point] == ':' && ((point+1 < line.length() && line[point+1] != '=') || point +1 == line.length())){
        cout<<"Lexical Error"<<endl;
        return -1;
    }
    int headPoint = point;
    point++;
    if ((line[headPoint] =='<' || line[headPoint]=='>' || line[headPoint]==':' )&&(point<line.length() && line[point]=='=')){
        //如果为两位的运算符
        point++;
    }
    string str = line.substr(headPoint,point-headPoint);
    sym.push_back("Keyword");
    label.push_back(str);
    out += str;
    out += "\n";
    return point;
}

//int main() {
//    out.clear();
//    while (getline(cin,line)){
//        int readPoint = 0;
//        while (readPoint < line.length()){
//            readPoint = calcKeyword(readPoint);
//            readPoint = calcNumber(readPoint);
//            readPoint = calcSymbol(readPoint);
//            if (readPoint == -1) return 0;
//        }
//    }
//    cout<<out;
//}

bool LexicalAnalyzer(vector<string>& sym, vector<string>& label){
    while (getline(cin,line)){
        int readPoint = 0;
        while (readPoint < line.length()){
            readPoint = calcKeyword(readPoint,sym,label);
            readPoint = calcNumber(readPoint,sym,label);
            readPoint = calcSymbol(readPoint,sym,label);
            if (readPoint == -1) return false;
        }
    }
    return true;
}


#endif //COMPILER_LEXICALANALYZER_H
